<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
  <title>history_test.html</title>
  <script src="test_bootstrap.js"></script>
  <script type="text/javascript">
    goog.require('bot');
    goog.require('bot.locators');
    goog.require('bot.test');
    goog.require('bot.window');
    goog.require('bot.userAgent');
    goog.require('goog');
    goog.require('goog.dom');
    goog.require('goog.events');
    goog.require('goog.testing.AsyncTestCase');
    goog.require('goog.testing.asserts');
    goog.require('goog.testing.jsunit');
    goog.require('goog.userAgent');
    goog.require('goog.userAgent.product');
  </script>
</head>
<body>
<iframe id="frame"></iframe>
<script type="text/javascript">
  var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
  // Set longer timeout due both to slowness in the Android emulator and
  // slowness in the loading of popup windows in all browsers.
  asyncTestCase.stepTimeout = 5000;

  var frame = null;
  var popup = null;
  var callback = null;

  // On Selenium-backed drivers (as used for Safari and Opera 10), the
  // window.opener property of popups has no properties, so we can't notify
  // this page when the popup has loaded (b/3504107). On Opera 11.5, the popup
  // blocker is currently enabled (b/5746540). On Webview (Android),
  // window.open will cause a dialog prompt that will cause load failure.
  // For these browsers, we test history in an iframe instead of a popup,
  // which limits the history properties we can reliably check.
  // TODO (gdennis): Use popups on all browsers once these bugs are fixed.
  if (bot.test.isSeleniumBacked() || goog.userAgent.product.ANDROID ||
      (goog.userAgent.OPERA && bot.userAgent.isEngineVersion(11.5))) {
    // A bug in prior versions of WebKit (persisting into Safari 5) causes the
    // initial page of an iframe to not enter the browser history, so we
    // initialize the iframe to a dummy page and the test cases here do not
    // make any assertions about this page being in the browser history.
    frame = bot.locators.findElement({'id': 'frame'});
    goog.events.listen(frame, 'load', notifyLoaded);
    continueAfterLoad('waiting for initial page load', function() {
      bot.setWindow(goog.dom.getFrameContentWindow(frame));
    });
    frame.src = 'testdata/history_page0.html';
  }

  function continueAfterLoad(desc, fn) {
    asyncTestCase.waitForAsync(desc);
    callback = fn;
  }

  function notifyLoaded() {
    // A dummy onunload event ensures the browser will not cache the page
    // and will fire a load event when on history.back() and forward(), see:
    // http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/
    bot.getWindow().onunload = goog.nullFunction;

    window.setTimeout(function() {
      asyncTestCase.continueTesting();

      // In some browsers, an error thrown outside of a test function will not
      // be caught and cause the test to fail, so we catch and set a flag that
      // is later caught during tearDown and causes the test to fail then.
      try {
        callback();
      } catch (e) {
        fail(e.toString());
      }
    }, 0);
  }

  function tearDown() {
    if (popup) {
      popup.close();
      popup = null;
    }
  }

  function load(url, fn) {
    var loc = window.location.href;
    url = loc.substring(0, loc.lastIndexOf('/') + 1) + url;
    continueAfterLoad('waiting for window to load ' + url, fn);
    if (popup || frame) {
      assertNotEquals('bot.setWindow() not called', bot.getWindow(), window);
      bot.getWindow().location.href = url;
    } else {
      popup = window.open(url);
      assertTrue('window.open() failed: is a pop-up blocker enabled?', !!popup);
      bot.setWindow(popup);
    }
  }

  function back(numPages, fn) {
    continueAfterLoad('waiting for browser to go back ' + numPages, fn);
    bot.window.back(numPages);
  }

  function forward(numPages, fn) {
    continueAfterLoad('waiting for browser to go forward ' + numPages, fn);
    bot.window.forward(numPages);
  }

  function assertUrlContains(str) {
    assertContains(str, bot.getWindow().location.href);
  }

  function testErrorThrownWhenNumPagesNonPositive() {
    assertThrows(goog.partial(bot.window.back, 0));
    assertThrows(goog.partial(bot.window.back, 0));
    assertThrows(goog.partial(bot.window.back, -1));
    assertThrows(goog.partial(bot.window.forward, -1));
  }

  function testErrorThrowWhenNumPagesNotLessThanHistoryLength() {
    // If not testing with popups, cannot check this property reliably,
    // because we cannot guarantee the history stack starts fresh.
    if (!popup) {
      return;
    }
    load('testdata/history_page1.html', function() {
      load('testdata/history_page2.html', function() {
        assertThrows(goog.partial(bot.window.back, 3));
        if (!goog.userAgent.OPERA &&
            (!goog.userAgent.WEBKIT || bot.userAgent.isEngineVersion('533'))) {
          assertThrows(goog.partial(bot.window.forward, 3));
        }
      });
    });
  }

  function testBackForwardOnePage() {
    load('testdata/history_page1.html', function() {
      load('testdata/history_page2.html', function() {
        back(1, function() {
          assertUrlContains('history_page1.html');
          forward(1, function() {
            assertUrlContains('history_page2.html');
          });
        });
      });
    });
  }

  function testBackForwardMultiplePages() {
    load('testdata/history_page1.html', function() {
      load('testdata/history_page2.html', function() {
        load('testdata/history_page3.html', function() {
          back(2, function() {
            assertUrlContains('history_page1.html');
            forward(2, function() {
              assertUrlContains('history_page3.html');
            });
          });
        });
      });
    });
  }
</script>
</body>
</html>
